﻿#include "dynamic_array.h"

static void InitArray(DynamicArray* arr, int init_capacity) {

    arr->data = (int*)malloc(init_capacity * sizeof(int));
    if (arr->data == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(-1);
    }

    arr->size = 0;

    arr->capacity = init_capacity;
}

static void Insert(DynamicArray* arr, int value) {

    if (arr->size == arr->capacity) {
        
        int new_capacity = arr->capacity *= 2;

        int *new_data = (int*)realloc(arr->data, new_capacity * sizeof(int));
        if (new_data == NULL) {
            fprintf(stderr, "Memory allocation failed\n");
            free(arr->data);
            exit(-1);
        }

        arr->data = new_data;
        arr->capacity = new_capacity;
    }

    arr->data[arr->size++] = value;
}

void Traverse(DynamicArray* arr) {
    
    for (int i = 0; i < arr->size; i++) {
        
        printf("%d ", arr->data[i]);
    }
    std::cout << std::endl;
}

void DeletaIndex(DynamicArray* arr, int index) {

    if (index < 0 || index >= arr->size) {

        printf("Index ouf of range.\n");

        return;
    }
    //boundary case
    if (index < arr->size - 1) {

        for (int i = index; i < arr->size - 1; i++) {

            arr->data[i] = arr->data[i + 1];

        }
    }

    arr->size--;

    if (arr->size == 0) {

        free(arr->data);

        arr->data = NULL;

        arr->capacity = 0;

    }else if (arr->size < arr->capacity / 4 && arr->capacity / 2 >= 2) {

        int new_capacity =  arr->capacity /= 2;

        int* new_data = (int*)realloc(arr->data, new_capacity * sizeof(int));

        if (new_data != NULL) {

            arr->data = new_data;
            arr->capacity = new_capacity;
        }
    }
}

void DeleteValue(DynamicArray* arr, int value) {
    
    for (int i = 0; i < arr->size; i++) {

        if (arr->data[i] == value) {

            DeletaIndex(arr, i);

            i--;

            break;
        }
    }
}

void DeleteAllElements(DynamicArray* arr) {

    while (arr->size > 0) {
        DeletaIndex(arr, 0);
    }  
    
}

void FreeArray(DynamicArray* arr) {

    free(arr->data);
    arr->data = NULL;
    arr->size = 0;
    arr->capacity = 0;
}

void TestDynamicArray1() {

    DynamicArray arr;
    InitArray(&arr, 2);

    //test insert
    Insert(&arr, 1);
    Insert(&arr, 2);
    Insert(&arr, 3);
    Insert(&arr, 4);
    printf("array1 after inserting :\n");
    Traverse(&arr);

    //test delete (index)
    DeletaIndex(&arr, 2);
    printf("After deleting element at index 2:\n");
    Traverse(&arr);

    //test delete (value)
    DeleteValue(&arr, 4);
    printf("After deleting element with 4:\n");
    Traverse(&arr);

    //delete all element
    DeleteAllElements(&arr);
    printf("After deleting all element:\n");
    Traverse(&arr);

    //test array size and capacity
    printf("Current size : %d\n", arr.size);
    printf("Current capacity: %d\n", arr.capacity);

    FreeArray(&arr);

    printf("array1 has been freed\n");
    printf("\n");
}
//test boundary case
void TestDynamicArray2() {

    DynamicArray arr;
    InitArray(&arr, 2);

    //test insert
    Insert(&arr, 1);
    Insert(&arr, 2);
    Insert(&arr, 3);
    Insert(&arr, 4);
    Insert(&arr, 2);

    printf("array2 after inserting :\n");
    Traverse(&arr);

    //test delete last element by index
    DeletaIndex(&arr, arr.size - 1);
    printf("After deleting last element :\n");
    Traverse(&arr);

    //again
    DeletaIndex(&arr, arr.size - 1);
    printf("After deleting new last element:\n");
    Traverse(&arr);

    //test delete (value)
    DeleteValue(&arr, 2);
    printf("After deleting element with 2:\n");
    Traverse(&arr);

    //delete all element
    DeleteAllElements(&arr);
    printf("After deleting all element:\n");
    Traverse(&arr);

    //test array size and capacity
    printf("Current size : %d\n", arr.size);
    printf("Current capacity: %d\n", arr.capacity);

    FreeArray(&arr);

    printf("array2 has been freed\n");
    printf("\n");
}

int main()
{
    TestDynamicArray1();

    //system("cls");
    TestDynamicArray2();


    return 0;
}


